<?php

namespace App\Services;

use Illuminate\Support\Facades\DB;
use Modules\Inventory\Repository\InventoryRepository;
use Modules\Inventory\Repository\InventoryTransRepository;
use App\Enums\InvTransType;
use Modules\Production\Repository\BoxTurnoverRepository;
use Modules\Production\Service\TaskScanService;

class InventoryService
{

    /**
     * 根据品号获取即时库存
     * @param String $materialNo
     * @return mixed
     */
    static public function getInventoryByMaterial(String $materialNo,$cargo = '',$orgCode = ''){
        return InventoryRepository::getInventoryByMaterialNo($materialNo,$cargo,$orgCode);
    }

    /**
     * 根据箱号查询即时库存
     * @param String $materialNo
     * @return mixed
     */
    static public function getInventoryByLotnum(String $lotnum,$cargo = '',$orgCode = ''){
        return InventoryRepository::getInventoryByLotnum($lotnum,$cargo,$orgCode);
    }

    /**
     * 根据库存ID分配库存
     * @param $docId
     * @param $docNo
     * @param $docType
     * @param $invId
     * @param $qty
     */
    static public function assignInvById($docId,$docNo,$docType,$invId,$qty){

        //1、将指定id库存
        $inv = InventoryRepository::getById($invId);

        //2、记录库存变动记录
        InventoryTransRepository::save([
            'org_code'      => $inv->org_code,
            'cargo_code'    => $inv->cargo_code,
            'supplier_code' => $inv->supplier_code,
            'doc_id'        => $docId,
            'docno'         => $docNo,
            'doc_type'      => $docType,
            'trans_type'    => InvTransType::ASSIGN->value,
            'material_no'   => $inv->material_no,
            'from_wms'      => TaskScanService::getWmsCodeByLocation($inv->location),
            'from_location' => $inv->location,
            'from_lotnum'   => $inv->lot_num,
            'from_unit'     => $inv->unit,
            'start_qty'     => $inv->qty,
            'end_qty'       => $inv->qty,
            'qty'           => $qty,
            'to_wms'        => TaskScanService::getWmsCodeByLocation($inv->location),
            'to_location'   => $inv->location,
            'to_lotnum'     => $inv->lot_num,
            'to_unit'       => $inv->unit,
        ]);

        InventoryRepository::incAssignQtyById($invId,$qty);

    }

    /**
     * 释放已分配库存
     * @param $docId
     * @param $docNo
     * @param $docType
     * @param $invId
     * @param $qty
     */
    static public function releaseAssign($docId,$docNo,$docType,$invId,$qty){

        $inv = InventoryRepository::getById($invId);

        InventoryRepository::releaseAssignQtyById($invId,$qty);
        InventoryTransRepository::save([
            'org_code'      => $inv->org_code,
            'cargo_code'    => $inv->cargo_code,
            'supplier_code' => $inv->supplier_code,
            'doc_id'        => $docId,
            'docno'         => $docNo,
            'doc_type'      => $docType,
            'trans_type'    => InvTransType::RELEASE->value,
            'material_no'   => $inv->material_no,
            'from_wms'      => TaskScanService::getWmsCodeByLocation($inv->location),
            'from_location' => $inv->location,
            'from_lotnum'   => $inv->lot_num,
            'from_unit'     => $inv->unit,
            'start_qty'     => $inv->qty,
            'end_qty'       => $inv->qty,
            'qty'           => $qty,
            'to_wms'        => TaskScanService::getWmsCodeByLocation($inv->location),
            'to_location'   => $inv->location,
            'to_lotnum'     => $inv->lot_num,
            'to_unit'       => $inv->unit,
        ]);

    }

    /**
     * 库存添加
     * [
     *      'org_code' => '组织代码'
     *      'cargo_code' => '货主代码'
     *      'supplier_code' => '供应商代码'
     *      'doc_id' => '入库单据ID',
     *      'docno' => '入库单据编号',
     *      'doc_type' => '单据类型',
     *      'material_no' => '物料编码',
     *      'location' => '库位',
     *      'qty' => '入库数量',
     *      'unit' => '单位编码',
     *      'lotnum' => '箱号',
     * ]
     * @param $data
     */
    static public function addInv($data){

        $startQty = 0;
        //1、判断相同库位相同箱号的库存是否存在，如果存在直接在原库存数据加增加数量，不存在则新增一条库存记录
        $hasInv = InventoryRepository::getInvByLocationAndLotnum($data['org_code'],$data['cargo_code'],$data['material_no'],$data['location'],$data['lotnum']);
        if($hasInv){
            $startQty = $hasInv->qty;
            //给原库存增加库存数量
            //InventoryRepository::updateByLocatonAndLotnum($data['cargo_code'],$data['material_no'],$data['location'],$data['lotnum'],$data['qty']);
            InventoryRepository::incrementQtyById($hasInv->id,$data['qty']);
        }else{

            //添加库存记录
            InventoryRepository::addIntentory([
                'org_code'      => $data['org_code'],
                'cargo_code'    => $data['cargo_code'],
                'supplier_code' => $data['supplier_code'] ?: '',
                'wms_code'      => TaskScanService::getWmsCodeByLocation($data['location']),
                'location'      => $data['location'],
                'material_no'   => $data['material_no'],
                'unit'          => $data['unit'],
                'qty'           => $data['qty'],
                'lot_num'       => $data['lotnum'],
            ]);

        }

        //2、库存变动记录入库
        InventoryTransRepository::save([
            'org_code'      => $data['org_code'],
            'cargo_code'    => $data['cargo_code'],
            'supplier_code' => $data['supplier_code'],
            'doc_id'        => $data['doc_id'],
            'docno'         => $data['docno'],
            'doc_type'      => $data['doc_type'],
            'trans_type'    => InvTransType::INBOUND->value,
            'material_no'   => $data['material_no'],
            'start_qty'     => $startQty,
            'end_qty'       => $startQty + $data['qty'],
            'qty'           => $data['qty'],
            'to_wms'        => TaskScanService::getWmsCodeByLocation($data['location']),
            'to_location'   => $data['location'],
            'to_lotnum'     => $data['lotnum'],
            'to_unit'       => $data['unit'],
            'from_wms'      => TaskScanService::getWmsCodeByLocation($data['location']),
            'from_location' => $data['location'],
            'from_lotnum'   => $data['lotnum'],
            'from_unit'     => $data['unit'],
        ]);
    }

    /**
     * 扣减库存（按分配数量扣减）
     * @param $docNo
     * @param $docId
     * @param $docType
     * @param $materialNo
     * @param $location
     * @param $lotnum
     * @param $qty
     * @return mixed
     * @throws \Exception
     */
    static public function decInventoryByAssign($docNo,$docId,$docType,$invId,$qty){

        //查询库存
        //$invInfo = InventoryRepository::getInvByLocationAndLotnum($caogoCode,$materialNo,$location,$lotnum);
        $invInfo = InventoryRepository::getById($invId);

        if(!$invInfo || ($invInfo->qty - $invInfo->lock_qty) < $invInfo->assign_qty){
            throw new \Exception('库存数量小于分配数量');
        }

        //扣减库存余量和分配库存
        InventoryRepository::decQtyAndAssignQtyById($invInfo->id,$qty);

        //保存库存扣减记录
        InventoryTransRepository::save([
            'org_code'      => $invInfo->org_code,
            'cargo_code'    => $invInfo->cargo_code,
            'supplier_code' => $invInfo->supplier_code,
            'doc_id'        => $docId,
            'docno'         => $docNo,
            'doc_type'      => $docType,
            'trans_type'    => InvTransType::OUTBOUND->value,
            'material_no'   => $invInfo->material_no,
            'start_qty'     => $invInfo->qty,
            'end_qty'       => $invInfo->qty - $qty,
            'qty'           => $qty,
            'from_wms'      => $invInfo->wms_code,
            'from_location' => $invInfo->location,
            'from_lotnum'   => $invInfo->lot_num,
            'from_unit'     => $invInfo->unit,
            'to_wms'        => $invInfo->wms_code,
            'to_location'   => $invInfo->location,
            'to_lotnum'     => $invInfo->lot_num,
            'to_unit'       => $invInfo->unit
        ]);

        return $invInfo;
    }

    /**
     * 按箱号直接扣减库存
     * @param $cargoCode 货主代码 
     * @param $docNo 单据编号
     * @param $docId 单据id
     * @param $docType 单据类型
     * @param $materialNo 品号
     * @param $location 库位代码
     * @param $lotnum 箱号
     * @param $qty 数量
     * @param $orgCode 组织代码
     */
    static public function decInventory($cargoCode,$docNo,$docId,$docType,$materialNo,$location,$lotnum,$qty,$orgCode = '103'){
        //查询库存
        $invInfo = InventoryRepository::getInvByLocationAndLotnum($orgCode,$cargoCode,$materialNo,$location,$lotnum);

        if(!$invInfo || ($invInfo->qty - $invInfo->lock_qty - $invInfo->assign_qty) < $qty){
            throw new \Exception("{$orgCode}-{$cargoCode}-{$materialNo}-{$location}-{$lotnum}-库存不足");
        }

        //扣减库存余量
        InventoryRepository::decQtyById($invInfo->id,$qty);

        //保存库存扣减记录
        InventoryTransRepository::save([
            'org_code'      => $invInfo->org_code,
            'cargo_code'    => $invInfo->cargo_code,
            'supplier_code' => $invInfo->supplier_code,
            'doc_id'        => $docId,
            'docno'         => $docNo,
            'doc_type'      => $docType,
            'trans_type'    => InvTransType::OUTBOUND->value,
            'material_no'   => $materialNo,
            'start_qty'     => $invInfo->qty,
            'end_qty'       => $invInfo->qty - $qty,
            'qty'           => $qty,
            'from_wms'      => TaskScanService::getWmsCodeByLocation($location),
            'from_location' => $location,
            'from_lotnum'   => $lotnum,
            'from_unit'     => $invInfo->unit,
            'to_wms'        => TaskScanService::getWmsCodeByLocation($location),
            'to_location'   => $location,
            'to_lotnum'     => $lotnum,
            'to_unit'       => $invInfo->unit
        ]);

        return $invInfo;
    }

    

}
